#!/usr/bin/env bash

# helper method
declare -f _contains_element > /dev/null || _contains_element() {
  local e match="$1"
  shift
  for e; do [[ "$e" == "$match" ]] && return 0; done
  return 1
}

_caddy_completions()
{
  # get current word, words array, current word index, and previous word, ignoring ":" as a wordbreak
  local cur cword words
  _get_comp_words_by_ref -n ":" cur words cword prev

  # complete subcommands list
  if [ "$cword" -eq "1" ] && [ "adapt build-info environ file-server fmt hash-password help list-modules reload reverse-proxy run start stop trust untrust validate version" != "" ]; then
    COMPREPLY=($(compgen -W "adapt build-info environ file-server fmt hash-password help list-modules reload reverse-proxy run start stop trust untrust validate version" -- "$cur"))
    __ltrim_colon_completions "$cur"
    return
  fi

  local subcommand="${words[1]}"

  local args used_flags used_args index

  # register completions for each subcommand
  if [ "${subcommand}" == "adapt" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--pretty" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi
      if [ "${args[0]}" == "--validate" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--adapter" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--config" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi

      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done

    if [[ "$prev" == "--adapter" ]]; then
      COMPREPLY=()
      if command -v grep > /dev/null && command -v sed > /dev/null && command -v tr > /dev/null; then
        COMPREPLY=($(compgen -W "$(caddy list-modules | grep adapters | sed s/caddy.adapters.// | tr '
' ' ')" -- "$cur"))
      fi
      return
    fi
    if [[ "$prev" == "--config" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -f -- "$cur"))
      return
    fi

    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--pretty" "${used_flags[@]}"; then
          completion+=("--pretty")
        fi
        if ! _contains_element "--validate" "${used_flags[@]}"; then
          completion+=("--validate")
        fi
        if ! _contains_element "--adapter" "${used_flags[@]}"; then
          completion+=("--adapter")
        fi
        if ! _contains_element "--config" "${used_flags[@]}"; then
          completion+=("--config")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "build-info" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi



      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done


    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi


      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "environ" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi



      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done


    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi


      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "file-server" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--browse" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi
      if [ "${args[0]}" == "--templates" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--domain" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--listen" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--root" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi

      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done

    if [[ "$prev" == "--domain" ]]; then
      COMPREPLY=()
      return
    fi
    if [[ "$prev" == "--listen" ]]; then
      COMPREPLY=()
      return
    fi
    if [[ "$prev" == "--root" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -d -- "$cur"))
      return
    fi

    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--browse" "${used_flags[@]}"; then
          completion+=("--browse")
        fi
        if ! _contains_element "--templates" "${used_flags[@]}"; then
          completion+=("--templates")
        fi
        if ! _contains_element "--domain" "${used_flags[@]}"; then
          completion+=("--domain")
        fi
        if ! _contains_element "--listen" "${used_flags[@]}"; then
          completion+=("--listen")
        fi
        if ! _contains_element "--root" "${used_flags[@]}"; then
          completion+=("--root")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "fmt" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--overwrite" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi


      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done


    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--overwrite" "${used_flags[@]}"; then
          completion+=("--overwrite")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi

    if [[ "${#used_args[@]}" -eq "0" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -f -- "$cur"))
      return
    fi

    return
  fi
  if [ "${subcommand}" == "hash-password" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi


      if [ "${args[0]}" == "--algorithm" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--plaintext" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--salt" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi

      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done

    if [[ "$prev" == "--algorithm" ]]; then
      COMPREPLY=()
      return
    fi
    if [[ "$prev" == "--plaintext" ]]; then
      COMPREPLY=()
      return
    fi
    if [[ "$prev" == "--salt" ]]; then
      COMPREPLY=()
      return
    fi

    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--algorithm" "${used_flags[@]}"; then
          completion+=("--algorithm")
        fi
        if ! _contains_element "--plaintext" "${used_flags[@]}"; then
          completion+=("--plaintext")
        fi
        if ! _contains_element "--salt" "${used_flags[@]}"; then
          completion+=("--salt")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "help" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi



      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done


    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi


      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi

    if [[ "${#used_args[@]}" -eq "0" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -W "adapt build-info environ file-server fmt hash-password help list-modules reload reverse-proxy run stop trust untrust validate" -- "$cur"))
      return
    fi

    return
  fi
  if [ "${subcommand}" == "list-modules" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--versions" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi


      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done


    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--versions" "${used_flags[@]}"; then
          completion+=("--versions")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "reload" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi


      if [ "${args[0]}" == "--adapter" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--config" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--address" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi

      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done

    if [[ "$prev" == "--adapter" ]]; then
      COMPREPLY=()
      if command -v grep > /dev/null && command -v sed > /dev/null && command -v tr > /dev/null; then
        COMPREPLY=($(compgen -W "$(caddy list-modules | grep adapters | sed s/caddy.adapters.// | tr '
' ' ')" -- "$cur"))
      fi
      return
    fi
    if [[ "$prev" == "--config" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -f -- "$cur"))
      return
    fi
    if [[ "$prev" == "--address" ]]; then
      COMPREPLY=()
      return
    fi

    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--adapter" "${used_flags[@]}"; then
          completion+=("--adapter")
        fi
        if ! _contains_element "--config" "${used_flags[@]}"; then
          completion+=("--config")
        fi
        if ! _contains_element "--address" "${used_flags[@]}"; then
          completion+=("--address")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "reverse-proxy" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--change-host-header" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--from" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--to" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi

      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done

    if [[ "$prev" == "--from" ]]; then
      COMPREPLY=()
      return
    fi
    if [[ "$prev" == "--to" ]]; then
      COMPREPLY=()
      return
    fi

    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--change-host-header" "${used_flags[@]}"; then
          completion+=("--change-host-header")
        fi
        if ! _contains_element "--from" "${used_flags[@]}"; then
          completion+=("--from")
        fi
        if ! _contains_element "--to" "${used_flags[@]}"; then
          completion+=("--to")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "run" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--environ" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi
      if [ "${args[0]}" == "--resume" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi
      if [ "${args[0]}" == "--watch" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--adapter" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--config" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--pingback" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--pidfile" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi

      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done

    if [[ "$prev" == "--adapter" ]]; then
      COMPREPLY=()
      if command -v grep > /dev/null && command -v sed > /dev/null && command -v tr > /dev/null; then
        COMPREPLY=($(compgen -W "$(caddy list-modules | grep adapters | sed s/caddy.adapters.// | tr '
' ' ')" -- "$cur"))
      fi
      return
    fi
    if [[ "$prev" == "--config" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -f -- "$cur"))
      return
    fi
    if [[ "$prev" == "--pingback" ]]; then
      COMPREPLY=()
      return
    fi
    if [[ "$prev" == "--pidfile" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -f -- "$cur"))
      return
    fi

    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--environ" "${used_flags[@]}"; then
          completion+=("--environ")
        fi
        if ! _contains_element "--resume" "${used_flags[@]}"; then
          completion+=("--resume")
        fi
        if ! _contains_element "--watch" "${used_flags[@]}"; then
          completion+=("--watch")
        fi
        if ! _contains_element "--adapter" "${used_flags[@]}"; then
          completion+=("--adapter")
        fi
        if ! _contains_element "--config" "${used_flags[@]}"; then
          completion+=("--config")
        fi
        if ! _contains_element "--pingback" "${used_flags[@]}"; then
          completion+=("--pingback")
        fi
        if ! _contains_element "--pidfile" "${used_flags[@]}"; then
          completion+=("--pidfile")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "start" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--watch" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi

      if [ "${args[0]}" == "--adapter" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--config" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--pidfile" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi

      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done

    if [[ "$prev" == "--adapter" ]]; then
      COMPREPLY=()
      if command -v grep > /dev/null && command -v sed > /dev/null && command -v tr > /dev/null; then
        COMPREPLY=($(compgen -W "$(caddy list-modules | grep adapters | sed s/caddy.adapters.// | tr '
' ' ')" -- "$cur"))
      fi
      return
    fi
    if [[ "$prev" == "--config" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -f -- "$cur"))
      return
    fi
    if [[ "$prev" == "--pidfile" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -f -- "$cur"))
      return
    fi

    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--watch" "${used_flags[@]}"; then
          completion+=("--watch")
        fi
        if ! _contains_element "--adapter" "${used_flags[@]}"; then
          completion+=("--adapter")
        fi
        if ! _contains_element "--config" "${used_flags[@]}"; then
          completion+=("--config")
        fi
        if ! _contains_element "--pidfile" "${used_flags[@]}"; then
          completion+=("--pidfile")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "stop" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi


      if [ "${args[0]}" == "--address" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi

      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done

    if [[ "$prev" == "--address" ]]; then
      COMPREPLY=()
      return
    fi

    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--address" "${used_flags[@]}"; then
          completion+=("--address")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "trust" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi



      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done


    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi


      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "untrust" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi


      if [ "${args[0]}" == "--ca" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--cert" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi

      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done

    if [[ "$prev" == "--ca" ]]; then
      COMPREPLY=()
      return
    fi
    if [[ "$prev" == "--cert" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -f -- "$cur"))
      return
    fi

    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--ca" "${used_flags[@]}"; then
          completion+=("--ca")
        fi
        if ! _contains_element "--cert" "${used_flags[@]}"; then
          completion+=("--cert")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "validate" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi


      if [ "${args[0]}" == "--config" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi
      if [ "${args[0]}" == "--adapter" ]; then
        used_flags+=("${args[0]}")
        args=("${args[@]:2}")
        index=$((index+2))
        continue
      fi

      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done

    if [[ "$prev" == "--config" ]]; then
      COMPREPLY=()
      COMPREPLY=($(compgen -f -- "$cur"))
      return
    fi
    if [[ "$prev" == "--adapter" ]]; then
      COMPREPLY=()
      if command -v grep > /dev/null && command -v sed > /dev/null && command -v tr > /dev/null; then
        COMPREPLY=($(compgen -W "$(caddy list-modules | grep adapters | sed s/caddy.adapters.// | tr '
' ' ')" -- "$cur"))
      fi
      return
    fi

    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi

        if ! _contains_element "--config" "${used_flags[@]}"; then
          completion+=("--config")
        fi
        if ! _contains_element "--adapter" "${used_flags[@]}"; then
          completion+=("--adapter")
        fi

      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
  if [ "${subcommand}" == "version" ]; then
    local args_shift=2
    # get the list of already used flags and args, ignoring the current word
    args=("${words[@]:args_shift}") # args without command and subcommand
    used_flags=()
    used_args=()
    index=0

    while [ "${#args[@]}" -gt 0 ]; do
      if [ "${index}" -eq "$((cword-args_shift))" ]; then
        # ignore current word
        args=("${args[@]:1}")
        index=$((index+1))
        continue
      fi



      if [[ "${args[0]}" != "-"* ]]; then
        used_args+=("${args[0]}")
      fi
      args=("${args[@]:1}")
      index=$((index+1))
    done


    if [[ $cur == -* ]]; then
      # flags
      completion=()

      if [[ $cur != --* ]]; then
        true
      fi


      COMPREPLY=($(compgen -W "${completion[*]}" -- "$cur"))
      return
    fi


    return
  fi
}

# register completion
complete -F _caddy_completions caddy

